﻿using System;
using Outlook = Microsoft.Office.Interop.Outlook;
using Core = Microsoft.Office.Core;
using Manager = OMC.DataManagement.Manager;
using StringResources = OMC.Properties.StringResources;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Resources;
using System.Runtime.InteropServices;
using System.Diagnostics;
using OMC.DataManagement;
using OMC.Utils;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using OMC.Classification;

namespace OMC.AddInHandling
{
    /// <summary>
    /// This class could manage all the things which are responsible of outlook actions.
    /// </summary>
    class AddInHandler
    {
        private Outlook.Stores stores;
        private Manager manager { get; set; }
        private String TextOfContextPopupMenu;
        private String TextOfContextMenuRefreshButton;
        private String TextofMailNotMoved;
        private String TextOfContextMenuSaveButton;
        private String TextOfSaveFileDialogFilter;
        private String TextOfSaveFileDialogTitle;
        private String TextOfContextMenuOptions;
        private Core.CommandBarPopup popUpMenu;
        private Core.CommandBarButton button;
        private ICollection<Outlook.MailItem> mailItems = new List<Outlook.MailItem>();

        /// <summary>
        /// The constructor to create an object of this class.
        /// </summary>
        /// <param name="stores">Outlook stores</param>
        /// <param name="manager">a manager object of class DataManagement.Manager</param>
        public AddInHandler(Outlook.Stores stores, DataManagement.Manager manager)
        {
            this.stores = stores;
            this.manager = manager;
            this.Init();
        }

        /// <summary>
        /// This method inits standard ressources and default folders.
        /// </summary>
        private void Init()
        {
            try
            {
                this.LoadResources();
                Logger.Write("Add In handler init");
            }
            catch (Exception ex)
            {
                String message = "It isn't possible to init the Handler";
                LoggerUtils.Write(message, ex, TraceEventType.Critical);
            }
        }

        /// <summary>
        /// This method loads the string resources of the text, which is shown in the user interface.
        /// There are language files based on the culture info. default file is "en"!
        /// </summary>
        /// <example>
        /// The cultureinfo convention, see:
        /// Source:http://msdn.microsoft.com/de-de/library/system.globalization.cultureinfo%28v=vs.80%29.aspx
        /// </example>
        private void LoadResources()
        {
            try
            {
                ResourceManager rm = StringResources.ResourceManager;
                //ContextMenu Strings
                TextOfContextPopupMenu = rm.GetString("ContextMenuPopupName");
                TextOfContextMenuRefreshButton = rm.GetString("ContextMenuRefresh");
                TextOfContextMenuOptions = rm.GetString("ContextMenuOption");
                TextOfContextMenuSaveButton = rm.GetString("ContextMenuSave");
                //SaveDialog Strigs
                TextOfSaveFileDialogFilter = rm.GetString("saveFileDialogFilter");
                TextOfSaveFileDialogTitle = rm.GetString("saveFileDialogTitle");
                //UserInfo Strings
                TextofMailNotMoved = rm.GetString("MailNotMoved");
            }
            catch (Exception ex)
            {
                String message = "It isn't possible to load Resources!";
                LoggerUtils.Write(message, ex, TraceEventType.Critical);
            }
        }

        /// <summary>
        /// This method creates a contextmenu item, which is type of popup menu.
        /// </summary>
        /// <param name="cmdBar">the command bar of the right clicked item</param>
        public void MakeContextPopUp(Core.CommandBar cmdBar)
        {
            try
            {
                //Create PopUpMenu in the ContextMenu
                popUpMenu = cmdBar.Controls.Add(Core.MsoControlType.msoControlPopup,
                                                         Type.Missing,
                                                         Type.Missing,
                                                         Type.Missing, true) as Core.CommandBarPopup;
                popUpMenu.BeginGroup = true;
                popUpMenu.Caption = TextOfContextPopupMenu;
                popUpMenu.Enabled = false;

                //set PopUpMenu Visible
                popUpMenu.Visible = true;
            }
            catch (COMException ex)
            {
                String message = "It isn't possible to create context popup menu";
                LoggerUtils.Write(message, ex, TraceEventType.Critical);
            }
        }

        /// <summary>
        /// This method handles the right click event on a mail item.
        /// </summary>
        /// <param name="commandBar">the Commandbar to be modified</param>
        /// <param name="selection">the Selection to determine the Mailitem</param>
        public void contextMenuDisplay(Core.CommandBar commandBar, Outlook.Selection selection)
        {
            if (selection == null)
            {
                return;
            }

            ICollection<IClassifiable> mailContents = new List<IClassifiable>();

            mailItems.Clear();
            foreach (Object obj in selection)
            {
                if (!(obj is Outlook.MailItem))
                {
                    return;
                }

                Outlook.MailItem mailItem = obj as Outlook.MailItem;
                if (mailItem == null)
                {
                    return;
                }
                mailItems.Add(mailItem);

                MailContent mailContent = new MailContent(mailItem.Body, mailItem.Subject, mailItem.SenderEmailAddress, mailItem.To);
                mailContents.Add(mailContent);
            }

            //Create context popup menu
            MakeContextPopUp(commandBar);

            //create ClassifiableCollection object from selected Maildata objects
            ClassifiableCollection multiMailContent = new ClassifiableCollection(mailContents);

            if (manager.textClassifier == null)
            {
                return;
            }

            //Classify selected items
            IEnumerable<TextClassifierResultItem> resultItems = manager.textClassifier.ClassifyTop(multiMailContent.GetContent());

            //Create the Context Menu
            MakeContextMenuButtons(commandBar, resultItems);
        }

        /// <summary>
        /// This method is used to create the context menu of
        /// each Mailitem with the associated Folder, classified by Weka.
        /// </summary>
        /// <example>
        /// Source CommandBar:  http://support.microsoft.com/kb/303018
        /// Source FaceID:      http://www.kebabshopblues.co.uk/2007/01/04/visual-studio-2005-tools-for-office-commandbarbutton-faceid-property/
        /// </example>
        /// <param name="cmdBar">this Commandbar could be modified</param>
        /// <param name="resultItems">the result items</param>
        public void MakeContextMenuButtons(Core.CommandBar cmdBar, IEnumerable<TextClassifierResultItem> resultItems)
        {
            if (resultItems == null)
            {
                return;
            }
            try
            {
                foreach (TextClassifierResultItem resultItem in resultItems)
                {
                    string[] split = resultItem.Class.Split(' ');
                    String entryId = split[0];
                    String storeId = split[1];
                    Outlook.Folder folder = null;
                    try
                    {
                        folder = (Outlook.Folder)manager.nameSpace.GetFolderFromID(entryId, storeId);
                    }
                    catch (COMException)
                    {
                        // folder not found
                        continue;
                    }
                    
                    
                    //Create Buttons to the PopUpMenu
                    button = popUpMenu.Controls.Add(Core.MsoControlType.msoControlButton,
                                                        Type.Missing,
                                                        Type.Missing,
                                                        Type.Missing, true) as Core.CommandBarButton;
                    button.Style = Core.MsoButtonStyle.msoButtonIconAndWrapCaption;
                    button.FaceId = 0133;
                    button.Caption = String.Format("{0} ({1:F1} %)", folder.Name, resultItem.Probability * 100);

                    //Set delegate to the ClickEventHandler
                    button.Click += new Core._CommandBarButtonEvents_ClickEventHandler(
                            (Core.CommandBarButton Cmd, ref bool Can) => TheButton_Click(Cmd, ref Can, entryId, storeId));
                    button.Visible = true;
                }

                //Set PopUpMenu enabled
                popUpMenu.Enabled = true;
            }
            catch (COMException ex)
            {
                String message = "It isn't possible to create buttons to context menu";
                LoggerUtils.Write(message, ex, TraceEventType.Critical);
            }
        }

        /// <summary>
        /// The method, which is called by a button events handler.
        /// </summary>
        /// <param name="cmdBarButton">the commandbar button, which called this method</param>
        /// <param name="Cancel">cancel</param>
        /// <param name="entryId"></param>
        /// /// <param name="storeId"></param>
        private void TheButton_Click(Core.CommandBarButton cmdBarButton, ref bool Cancel, String entryId, String storeId)
        {
            try
            {
                Outlook.Folder folder = (Outlook.Folder)manager.nameSpace.GetFolderFromID(entryId, storeId);
                try
                {
                    foreach (Outlook.MailItem mailItem in this.mailItems)
                    {
                        mailItem.Move(folder); // this will be catched by BeforeItemMoved...
                    }
                }
                catch (COMException ex)
                {
                    LoggerUtils.Write("Cannot move mailItem to folder", ex, TraceEventType.Error);
                }

            }
            catch (COMException ex)
            {
                LoggerUtils.Write("Error while moving mail items.", ex, TraceEventType.Error);
            }

        }
    }
}